unit udxaudio;

interface
uses
  classes,windows,activex, DirectSound,DirectMusic, DirectDraw;

type

   TSoundCollection=class(TCollection)
   private
     FLoader:IDirectMusicLoader8;
     FPerformance:IDirectMusicPerformance8;
   public
     constructor Create(ItemClass:TCollectionItemClass);
     destructor Destroy;override;
   end;

   TSoundItem=class(TCollectionItem)
   private
     FSegment:IDirectMusicSegment8;
     FSegmentState:IDirectMusicSegmentState8;
     FAudioPath:IDirectMusicAudioPath8;
     FSoundCollection:TSoundCollection;
     FInternalStream:TMemoryStream;
     FLooped: boolean;
     function GetIsPlaying:boolean;
     procedure SetSegmentLoop(const loop:boolean);
     procedure SetLooped(const Value: boolean);
   protected
     procedure Init;virtual;
   public
     constructor Create(Collection:TCollection);override;
     destructor Destroy;override;
     function Play:HResult;
     function Stop:HResult;
     procedure LoadFromFile(const filename:string);
     procedure LoadFromStream(Stream:TStream);
   published
     property IsPlaying:boolean read GetIsPlaying;
     property Looped:boolean read FLooped write SetLooped;
   end;


implementation

{ TSoundItem }

constructor TSoundItem.Create(Collection: TCollection);
begin
  inherited;
  FSoundCollection:=Collection as TSoundCollection;
  Init;
end;

destructor TSoundItem.Destroy;
begin
  FSegment.Unload(FAudioPath);

  FSegment:=nil;
  FSegmentState:=nil;
  FAudioPath:=nil;

  FInternalStream.Free;
  inherited;
end;

function TSoundItem.GetIsPlaying: boolean;
begin
  result:=(FSegment<>nil);
end;

procedure TSoundItem.Init;
begin
  FSoundCollection.FPerformance.CreateStandardAudioPath(
                       DMUS_APATH_SHARED_STEREOPLUSREVERB,
                       64,true,
                       FAudioPath);
end;

procedure TSoundItem.LoadFromFile(const filename: string);
var afilename:widestring;
begin
  afilename:=filename;
  FSoundCollection.FLoader.LoadObjectFromFile(CLSID_DirectMusicSegment,
                               IDirectMusicSegment8,PWideChar(aFilename),
                               FSegment);
  FSegment.Download(FAudioPath);
  SetSegmentLoop(FLooped);
end;

procedure TSoundItem.LoadFromStream(Stream: TStream);
var objdesc:TDMus_ObjectDesc;
begin
  if FInternalStream=nil then
    FInternalStream:=TMemoryStream.Create
  else
  begin
    FInternalStream.Clear;
  end;

  FInternalStream.CopyFrom(Stream,0);

  ZeroMemory(@objDesc,sizeof(TDMus_ObjectDesc));
  objdesc.dwSize:=sizeof(TDMus_ObjectDesc);
  objdesc.dwValidData:=DMUS_OBJ_CLASS or DMUS_OBJ_MEMORY;
  objdesc.guidClass:=CLSID_DirectMusicSegment;
  objdesc.llMemLength:=FInternalStream.Size;
  objdesc.pbMemData:=FInternalStream.Memory;

  FSoundCollection.FLoader.GetObject(objdesc,
                     IDirectMusicSegment8,
                     FSegment);
  FSegment.Download(FAudioPath);
  SetSegmentLoop(FLooped);
end;

function TSoundItem.Play: HResult;
var aseg:IDirectMusicSegmentState;
begin
  result:=FSoundCollection.FPerformance.PlaySegmentEx(FSegment,
                  nil,
                  nil,
                  DMUS_SEGF_SECONDARY,
                  0,
                  @aseg,
                  nil,
                  FAudioPath
                  );
  //aseg.QueryInterface(IDirectMusicSegmentState8,FSegmentState);
end;

procedure TSoundItem.SetLooped(const Value: boolean);
begin
  if FLooped<>Value then
  begin
    FLooped := Value;
    SetSegmentLoop(FLooped);
  end;
end;

procedure TSoundItem.SetSegmentLoop(const loop: boolean);
var loop_count:cardinal;
begin
  if FSegment<>nil then
  begin
    if loop then
      loop_count:=DMUS_SEG_REPEAT_INFINITE
    else
      loop_count:=0;

    FSegment.SetRepeats(loop_count);
  end;
end;

function TSoundItem.Stop: HResult;
begin
  result:=FSoundCollection.FPerformance.StopEx(FSegment,0,0);
end;

{ TTSoundCollection }

constructor TSoundCollection.Create(ItemClass: TCollectionItemClass);
begin
  inherited;
  CoCreateInstance(CLSID_DirectMusicPerformance,
                   nil,
                   CLSCTX_INPROC,
                   IDirectMusicPerformance8,
                   FPerformance);
  CoCreateInstance(CLSID_DirectMusicLoader,
                   nil,
                   CLSCTX_INPROC,
                   IDirectMusicLoader8,
                   FLoader);

  FPerformance.InitAudio(nil,
                         nil,
                         0,
                         DMUS_APATH_SHARED_STEREOPLUSREVERB,
                         64,
                         DMUS_AUDIOF_ALL,
                         nil
                         );
end;

destructor TSoundCollection.Destroy;
begin
  inherited;
  FLoader:=nil;
  FPerformance.CloseDown;
  FPerformance:=nil;
end;


initialization
  CoInitialize(nil);
finalization
  CoUninitialize;
end.
